﻿<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8" />
    <title></title>
    <style></style>
</head>

<body>
    <script src="JS/jquery.min.js"></script>
    <link href="css/bootstrap.min.css" rel="stylesheet" />
    <link href="css/css/font-awesome.min.css" rel="stylesheet" />
    <link href="JS/layer/theme/default/layer.css" rel="stylesheet" />
    <script src="JS/layer/layer.js"></script>
    <link href="js/EasyUI/themes/insdep/easyui.css" rel="stylesheet" />
    <script src="js/EasyUI/jquery.easyui.min.up.js"></script>
    <script src="js/EasyUI/easyui-lang-zh_CN.js"></script>
    <script src="js/EasyUI/extension/columns-ext.js"></script>
    <script src="JS/init.js"></script>
    <script src="JS/jquery.extend.js"></script>
    <script src="JS/vue.js"></script>
    <script src="JS/vue-json-view.js"></script>
    <script src="JS/stacktrace.js"></script>
    <br />
    <div id="outermost" class="easyui-layout" style="width:100%;height:1050px;">
        <div data-options="region:'center',boder:false">
            <div id="cc" class="easyui-layout" fit="true">
                <div data-options="region:'center',boder:false">
                    <e_autoform id="sel_form1" formUrl="/WebLogIndex/Get/getSearchDto" rowShowCount="4">
                    </e_autoform>
                </div>
                <div data-options="region:'east',boder:false" style="width:1px;">
                    <input id="__mode" class="easyui-switchbutton" style="width:80px"
                           data-options='"onText":"新模式","offText":"旧模式","onChange":newModel.change' />
                    <span style="display:none" class="searchTableBtns">
                        <input id="notSymbolSel" class="easyui-combobox" />
                        <input id="fieldSel" class="easyui-combobox" />
                        <input id="symbolSel" class="easyui-combobox" />
                        <input id="valBox" class="easyui-textbox" />
                        &nbsp;&nbsp;<a onclick="newModel.and()">and</a>&nbsp;&nbsp;<a onclick="newModel.or()">or</a>&nbsp;&nbsp;&nbsp;<a onclick="newModel.search()">查询</a>&nbsp;&nbsp;&nbsp;<a onclick="newModel.clearData()">重置</a>&nbsp;&nbsp;&nbsp;&nbsp;
                    </span>
                    <input id="searchTable" style="display:none" />
                </div>
            </div>
        </div>
        <div data-options="region:'east',split:true,boder:false" style="width:48%;">
            <input id="dtoSlider" class="easyui-slider" value="100" style="width:600px;"
                   data-options="showTip:true,height:'50px'" />
            <input id="cellText" class="easyui-textbox" data-options="iconCls:'icon-search',multiline:'true',fit:'true'"
                   style="">
        </div>
        <div data-options="region:'south',split:true,boder:false" style="height:920px;">
            <div class="easyui-layout" style="height:900px;">
                <div data-options="region:'center',split:true,boder:false" style="height:500px;">
                    <table id="dg"></table>
                </div>
                <div data-options="region:'south',split:true,boder:false" style="height:400px;">
                    <div class="easyui-layout" style="width:100%;height:400px;">
                        <div data-options="region:'center'">
                            <div id="jsonCell"></div>
                        </div>
                        <div data-options="region:'east',split:true" style="width:30%;">
                            <div id="jsonRow"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div>
    </div>
    <br />
    <br />
    <br />
    <a id="changeConfig" onclick="dialog.open()" href="#" class="btn btn-success"><i class="fa fa-check"></i>修改配置</a>
    <a onclick="openSwagger()" href="#" class="btn"><i class="fa fa-check"></i>打开Swagger</a>
    <a id="logPathBtn" onclick="LogPath.open()" href="#" class="btn btn-success"><i class="fa fa-info"></i>修改监听配置</a>
    <a id="sysLogBtn" onclick="SysLog.open()" href="#" class="btn btn-success"><i class="fa fa-info"></i>查看系统日志</a>
    <a id="showAnalyze" onclick="__search.showAnalyze()" href="#" class="btn btn-success"><i class="fa fa-info"></i>api分析</a>
    <!--弹出框-->
    <div style="display:none;">
        <e_dialog id="dialog-changeConfig" formurl="/WebLogIndex/Get/config" savefunc="dialog.save">
        </e_dialog>
        <e_dialog id="logPathDialog" formurl="/WebLogIndex/Get/logPath" savefunc="LogPath.saveCall">
            <div>
                <a id="logPathAdd" onclick="LogPath.add()" href="#" class="btn btn-success">
                    <i class="fa fa-plus "></i>新增
                </a>
            </div>
            <table id="logPathDg"></table>
        </e_dialog>
        <e_dialog id="logDialog" formurl="/WebLogIndex/Get/sysLog" rowShowCount="4">
            <table id="SysLogDG"></table>
        </e_dialog>
    </div>
    <!--需要在正文下面 解析用的js-->
    <script src="JS/easyUIByVueExten.js"></script>
    <script src="js/activate-power-mode.js"></script>
    <script>
        POWERMODE.colorful = true; // make power mode colorful
        POWERMODE.shake = false; // turn off shake
        document.body.addEventListener('input', POWERMODE);
    </script>
    <script>
        alert = comFunc.alert;
        let newModel = {
            show() {
                $('#cc').layout("panel", 'east').panel({
                    'width': $('#cc').width()
                });
                $('#cc').layout("resize");
                $('#outermost').layout("panel", 'north').panel({
                    'height': 240
                });
                $('#outermost').layout("resize");
            },
            hide() {
                $('#cc').layout("panel", 'east').panel({
                    'width': 1
                });
                $('#cc').layout("resize");
                $('#outermost').layout("panel", 'north').panel({
                    'height': 210
                });
                $('#outermost').layout("resize");
            },
            change(nv) {
                let funcName;
                if (nv) {
                    funcName = 'show';
                } else {
                    funcName = 'hide';
                }
                newModel[funcName]();
                $('.searchTableBtns')[funcName]();
                if (nv && !$('#searchTable').data('datagrid')) {
                    $('#searchTable').datagrid({
                        fit: false,
                        columns: [
                            [{
                                    field: 'field',
                                    title: '字段名',
                                    align: 'center',
                                    width: '180'
                                },
                                {
                                    field: 'symbol0',
                                    title: '符号',
                                    align: 'center',
                                    width: '60'
                                },
                                {
                                    field: 'val0',
                                    title: '值',
                                    align: 'center',
                                    width: '150'
                                },
                            ]
                        ],
                        onLoadSuccess: function () {
                            let fs = $(this).datagrid('getColumnFields');
                            comFunc.cellShowTips('#searchTable', fs);
                        },
                        onDblClickCell: function (index, field, value) {
                            let rows = $(this).datagrid('getRows');
                            if (!rows) return;
                            let row = rows[index];
                            if (row.oldRow && (row.field === 'or' || row.field === 'and')) {
                                row.oldRow.isAnd = !row.oldRow.isAnd;
                                newModel.loadData();
                            } else if (field !== 'field') {
                                let isNot = row.field.indexOf('not ') === 0;
                                let _field = isNot ? row.field.split(' ')[1] : row.field;
                                let m = field.match(/(\d+)$/);
                                if (!m) return;
                                let val = row['val' + m[1]];
                                let symbol = row['symbol' + m[1]];
                                $('#notSymbolSel').combobox('setValue', isNot ? 'not' : 'notnot');
                                $('#fieldSel').combobox('setValue', _field);
                                $('#symbolSel').combobox('setValue', symbol);
                                $('#valBox').textbox('setValue', val);
                            }
                        },
                    });
                } else $('#searchTable').parents('.panel .datagrid').eq(0)[funcName]();
            },
            _data: {},
            _datas: [],
            _maxCount: 0,
            getData() {
                return this._data;
            },
            getSelData() {
                //依次从后往前 _datas 现在先不处理
                //放到
                // 字段名 符号 值；  BigNode(:node),logicalSymbol   ,node prev, node next | 逻辑符号
                let baseNodeCreate = (filed, symbol, val, not = false) => {
                    if (symbol === 'like' && val === '%%') val = '';
                    let arr = [];
                    if ((arr = filed.split(' ')).length > 1) {
                        not = true;
                        filed = arr[1];
                    }
                    return {
                        filed: filed,
                        symbol: symbol,
                        val: val,
                        not: not
                    };
                };
                let union = (prevNode, unionLogicalSymbol, nextNode) => {
                    prevNode.unionLogicalSymbol = unionLogicalSymbol;
                    prevNode.next = nextNode;
                    nextNode.prev = prevNode;
                    return nextNode;
                }
                let node = null,
                    fNode = null;
                let lastLogicalSymbol = '';
                let dataParse = (data) => {
                    if (typeof (data) !== 'object') return;
                    if (node != null && data['isData'] === false) {
                        //连接符号处理
                        lastLogicalSymbol = data['isAnd'] ? 'and' : 'or';
                    } else {
                        let keyCount = Object.keys(data).length,
                            idx = 0;
                        let _fNode = null,
                            _lNode = null;
                        for (let i in data) {
                            if (typeof (data[i]) === 'object') {
                                for (let j in data[i]) {
                                    if (data[i][j]) {
                                        let curNode = baseNodeCreate(i, j, data[i][j]);
                                        if (node === null) {
                                            fNode = node = curNode;
                                        } else {
                                            node = union(node, lastLogicalSymbol || 'and', curNode);
                                            lastLogicalSymbol = '';
                                        }
                                        if (idx === 0 && !_fNode) {
                                            _fNode = node;
                                        }
                                        if (idx === keyCount - 1) {
                                            _lNode = node;
                                        }
                                    }
                                }
                            }
                            idx++;
                        }
                        if (_fNode !== _lNode && _fNode && _lNode) {
                            _fNode.nodeType = 1;
                            _lNode.nodeType = 2;
                        } else if (_fNode === _lNode && _fNode) _fNode.nodeType = 3;
                    }
                };
                let data = this.getData();
                let datas = [];
                if (Array.isArray(this._datas))
                    for (let i = this._datas.length; i > 0;)
                        datas.push(this._datas[--i]);
                datas.forEach(d => dataParse(d));
                dataParse(data);
                return fNode;
            },
            search(isNotRecord) { //还需要括号功能
                let data = search.getSearchData();
                if (!data) return;
                data = {
                    skip: data['skip'],
                    memo: data['memo'],
                    take: data['take'],
                    pageSize: data['pageSize'],
                    currentPageIndex: data['currentPageIndex']
                };
                data['isNewMode'] = true;
                data['isNotRecord'] = isNotRecord ? true : false;
                data['node'] = this.getSelData();
                comFunc.delayExecFunc('pageMain_searchFuncExec', () => {}, 10);
                dg('load', data);
                search.setRecord();
            },
            and_or(isAnd) {
                let dt;
                if (Object.keys(dt = this.getData()).length === 0) return;
                //当前的添加到数组里面
                let arr = [{
                    isAnd: isAnd,
                    isData: false
                }, dt];
                this._datas = arr.concat(this._datas);
                this._data = {};
                this.loadData($('#fieldSel').combobox('getValue'));
            },
            and() {
                this.and_or(true);
            },
            or() {
                this.and_or();
            },
            loadData(field, data = null) {
                let isAllData = data === null;
                data = data || this.getData();
                let obj = {},
                    maxCount = this._maxCount,
                    gridData = [];
                let addField = (f) => {
                    if (typeof (data[f]) !== 'object') return;
                    let keys = Object.keys(data[f]),
                        keyCount = keys.length;
                    if (keyCount > maxCount) maxCount = keyCount;
                    let row = {
                        field: f
                    };
                    let hasVal = false;
                    for (let j = 0; j < keyCount; j++) {
                        row['symbol' + j] = keys[j];
                        row['val' + j] = data[f][keys[j]] || '';
                        if (row['val' + j]) {
                            if (row['symbol' + j] === 'like' && row['val' + j] === '%%');
                            else hasVal = true;
                        }
                    }
                    hasVal && gridData.push(row);
                };
                if (field) {
                    if ($('#notSymbolSel').combobox('getValue') === 'not')
                        field = 'not ' + field;
                    obj[field] = data[field];
                    addField(field);
                }
                for (let i in data) {
                    if (i === field) continue;
                    obj[i] = data[i];
                    addField(i);
                }
                if (this._maxCount !== maxCount) {
                    this._maxCount = maxCount;
                    let columns = [{
                            field: 'field',
                            title: '字段名',
                            align: 'center',
                            width: '180'
                        },
                        {
                            field: 'symbol0',
                            title: '符号',
                            align: 'center',
                            width: '60'
                        },
                        {
                            field: 'val0',
                            title: '值',
                            align: 'center',
                            width: '100'
                        },
                    ];
                    for (let j = 1; j < this._maxCount; j++) {
                        columns.push({
                            field: `symbol${j}`,
                            title: '符号',
                            align: 'center',
                            width: '60'
                        });
                        columns.push({
                            field: `val${j}`,
                            title: '值',
                            align: 'center',
                            width: '60'
                        });
                    }
                    $('#searchTable').datagrid({
                        columns: [columns]
                    });
                }
                //处理 and or
                if (isAllData && this._datas.length > 0) {
                    this._datas.forEach(d => {
                        if (d['isData'] === false) {
                            gridData.push({
                                field: d['isAnd'] ? 'and' : 'or',
                                oldRow: d
                            });
                        } else {
                            gridData = gridData.concat(newModel.loadData(field, d));
                        }
                    });
                }
                $('#searchTable').datagrid('loadData', gridData);
                this._data = obj;
                return gridData;
            },
            clearData() {
                this._datas = [];
                this._data = {};
                this.loadData();
            },
            init() {
                $('#notSymbolSel').combobox({
                    width: 80,
                    value: 'notnot',
                    onChange(nv) {
                        newModel.getOrSetCurVal();
                        newModel.loadData($('#fieldSel').combobox('getValue'));
                    },
                }).combobox('loadData', [{
                    text: '正常',
                    value: 'notnot'
                }, {
                    text: '取反',
                    value: 'not'
                }]);
                $('#fieldSel').combobox({
                    onSelect: newModel.fieldSelChange
                });
                $('#symbolSel').combobox({
                    width: 60,
                    onHidePanel: newModel.symbolSelHidePanel
                });
                $('#valBox').textbox({
                    onChange(nv) {
                        newModel.getOrSetCurVal(() => nv);
                        newModel.loadData($('#fieldSel').combobox('getValue'));
                    }
                });
                $(() => {
                    if (search.vue && search.vue.fields //存在字段时 加载字段选择
                        &&
                        Array.isArray(search.vue.fields) && search.vue.fields.length > 0) {

                        let data = search.vue.fields.filter(f => ['endTime', 'completeEnd'].indexOf(f
                            .controlName) === -1).map(f => new Object({
                            value: f.controlName,
                            text: `${f.lableName}${f.controlName ? ' | ' + f.controlName : ''}`,
                            expressionArr: ['= 1', 'and', 'like 2', 'and', ['like 3', 'or',
                                '=4'
                            ]] //a, and, b, and ,[c,or,d]
                        })); //false && false || false || true 不建议这种格式 读不懂
                        data.filter(f => f.value === 'beginTime').forEach(f => {
                            f.value = 'date';
                            f.text = '时间 | date';
                        });
                        data.filter(f => f.value === 'completeBegin').forEach(f => {
                            f.value = 'complete';
                            f.text = '耗时 | complete';
                        });
                        $('#fieldSel').combobox('loadData', [{
                            value: '',
                            text: '请选择字段'
                        }].concat(data));
                        let symbols = ['like', 'in', '=', '!=', '>=', '>', '<=', '<'];
                        $('#symbolSel').combobox('loadData', symbols.map(s => new Object({
                            value: s,
                            text: s
                        })));
                    }
                });
                //把vue的东西给变成下拉框
                //name 取 拼音
            },
            fieldSelChange: function (row) { //改变后显示符号下拉框，符号下拉框有值的话不显示 没有值就显示
                console.log(row);
                if (!row.value) return;
                newModel.loadData(row.value);
                let sVal = $('#symbolSel').combobox('getValue');
                if (sVal) { //有值 重排序
                    newModel.toValBox();
                } else {
                    $('#symbolSel').combobox('showPanel');
                }
                if (Array.isArray(row['expressionArr']) && row['expressionArr'].length > 0) {
                    //debugger
                    //符号使用颜色
                    //括号使用颜色  堆栈模式吧 用不同组颜色
                    //show idx color vue
                    //console.log(row.expressionArr);
                }
            },
            symbolSelHidePanel() { //下拉框隐藏 得到已经选择的值 并显示出来
                let val = '';
                if (val = $(this).combobox('getValue')) {
                    newModel.toValBox();
                    if (val === 'like') {
                        $('#valBox').textbox('setValue', '%%')
                    }
                }
            },
            toValBox() { //跳转到值的输入
                let val = newModel.getOrSetCurVal();
                $('#valBox').textbox('setValue', val);
                newModel.loadData($('#fieldSel').combobox('getValue'));
            },
            getOrSetCurVal(getVal) { //根据字段等 获取val
                let fieldVal = $('#fieldSel').combobox('getValue'),
                    symbolVal = $('#symbolSel').combobox('getValue');
                if (!fieldVal || !symbolVal) return '';
                if ($('#notSymbolSel').combobox('getValue') === 'not') {
                    fieldVal = 'not ' + fieldVal;
                }
                let data = newModel.getData();
                data[fieldVal] = data[fieldVal] || {}; //数组结构 可以多维数组来代表括号 一个数组就是 一组条件 第二个就是or
                //一个字段一个符号可以有多个含义 默认先按照 一个个简单的来吧
                data[fieldVal][symbolVal] = data[fieldVal][symbolVal] || '';
                if (typeof (getVal) !== 'function') return data[fieldVal][symbolVal];
                else return data[fieldVal][symbolVal] = getVal();
            },
            parseNode(node) {
                // 反解开  查询 需要防止注入  要加入not
                //同时能自由组合括号也许比较好 目前一个data一个大括号
                //顺序是 第一层在最底下 最下面一层在最上面
                let _datas = [];
                let _data = {};
                while (node) {
                    let f = (node.not === true ? 'not ' : '') + node['filed'];
                    let curFileds = _data[f] = _data[f] || {};
                    curFileds[node['symbol']] = node['val'] || '';
                    if (node['nodeType'] === 3 || node['nodeType'] === 2 || node['unionLogicalSymbol'] === 'or') {
                        _datas.push(_data);
                        if (node['nodeType'] === 3 || node['unionLogicalSymbol'] === 'or') {
                            //把符号加进去
                            _datas.push({
                                isAnd: node['unionLogicalSymbol'] !== 'or',
                                isData: false
                            });
                        }
                        _data = {};
                    }
                    node = node['next'];
                }
                _datas.reverse();
                if (Object.keys(_data).length === 0 && _datas[0]['isData'] !== false) {
                    _data = _datas[0];
                    _datas.removeAt(0);
                } else if (_datas[0]['isData'] === false) {
                    _datas.removeAt(0);
                    _data = _datas[0];
                    _datas.removeAt(0);
                }
                this._data = _data;
                this._datas = _datas;
                this.loadData();
            }
        };
        let search = {
            vue: $('#sel_form1').data('vue'),
            getControl: $('#sel_form1').data('getControl'),
            lastSelCall: undefined, //下一次查询的回调
            search_btn: {
                isInit: false,
                getSearchBtnText(s) {
                    if (s == 0) return `<i class="fa fa-search"></i>查询`;
                    return `<i class="fa fa-search fa-spin"></i>查询${(s ? `(${s})` : s)}`;
                },
                set_search_delay() {
                    let search_delay = comFunc.getCookie('search_delay') || search.search_delay;
                    $.messager.prompt('查询间隔调整', `请输入自动触发查询的间隔秒数(目前为止${search_delay})：`, (r) => {
                        if (r === '' || r === undefined) return comFunc.alert('取消设置');
                        let v = parseInt(r);
                        if (isNaN(v) || r < 0 || r > 30) {
                            comFunc.alert('请输入一个0~30的数字');
                            this.set_search_delay();
                        } else {
                            if (v == 0) {
                                comFunc.alert('建议大于0，因为多个查询同时触发，会导致得到的查询可能有问题');
                            }
                            search.search_delay = v;
                            comFunc.setCookie('search_delay', v);//每次刷写一次
                        }
                    });
                },
                show: () => $('#search_btnDiv').show(),
                hide: function () {
                    if (search.search_delay <= 0) {
                        $('#search_btnDiv').show();
                        $('#search_btn,#search_btn_cancel').hide();
                    } else {
                        $('#search_btnDiv').hide();
                        $('#search_btn,#search_btn_cancel').show();
                    }
                    this.tipIdxs.forEach(e => layer.close(e));
                    this.tipIdxs = [];
                },
                change(s, isOverHide = true) {
                    if (!this.isInit) this.init(s);
                    $('#search_btn').html(this.getSearchBtnText(s));
                    if (isOverHide && s == 0) {//超时就隐藏
                        this.hide();
                    }
                    else {
                        this.show();
                    }
                },
                tipIdxs: [],
                init(s) {
                    let search_delay = comFunc.getCookie('search_delay') || search.search_delay;
                    comFunc.setCookie('search_delay', search_delay);//每次刷写一次
                    search.search_delay = parseInt(search_delay);
                    $('#search_btnDiv').remove();
                    $('#sel_form1').append(`<span id="search_btnDiv"style="position:fixed;right:53%;top:90px">
                        <a class="btn btn-info" id="search_btn">
                            ${this.getSearchBtnText(s)}
                        </a>
                        <a class="btn btn-info" id="search_btn_cancel">
                            <i class="fa fa-stop-circle"></i>停
                        </a>
                        <a class="btn btn-info" id="search_btn_set">
                            <i class="fa fa-cog"></i>
                        </a>
                    </span>`);

                    $('#search_btn').mousemove(e => {
                        this.tipIdxs.push(layer.tips('点击可以立即查询', '#search_btn', { tips: 3 }));
                    }).click(() => {
                        search.searchFunc(0);
                        this.change(0);
                    });
                    $('#search_btn_cancel').mousemove(e => {
                        this.tipIdxs.push(layer.tips('点击可取消延时查询', '#search_btn_cancel', {tips: 3}));
                    }).click(() => {
                        clearTimeout(window["pageMain_searchFuncExec"]);
                        this.change(0, false);
                    });
                    $('#search_btn_set').mousemove(e => {
                        this.tipIdxs.push(layer.tips('点击可设置之后自动触发的查询间隔', '#search_btn_set', { tips: 3 }));
                    }).click(() => {
                        this.set_search_delay();
                    });
                    this.hide();
                    this.isInit = true;
                }
            },
            showAnalyze: function () {
                //$.post('/weblogApi/Analyze', {}).then(data => {
                //    if (comFunc.handelError(data)) return;
                //});
                layer && layer.open({ //打开layer弹出框
                    area: ['70%', '600px'],
                    type: 1, //类型
                    maxmin: true,
                    shade: false,
                    title: "API运行分析", //定义标题
                    content: `
	    <div id="AnalyzeBar">
		    <input id="beginTime"/><input id="endTime"/>
	    </div>
	    <table id="dgAnalyze" toolbar="#AnalyzeBar"></table>`, //输出的字符串，定义弹出框的html页面
                    btn: ['确定', '取消'], //按钮
                    success() {
                        $('#AnalyzeBar>#beginTime').datetimebox({ value: (new Date()).AddDay(0) });
                        $('#AnalyzeBar>#endTime').datetimebox({ value: (new Date()).AddDay(1) });
                        $('#dgAnalyze').datagrid({
                            fit: true,
                            height: 800,
                            url: '/weblogApi/Analyze',
                            queryParams: {
                                beginTime: () => $('#AnalyzeBar>#beginTime').val(),
                                endTime: () => $('#AnalyzeBar>#endTime').val(),
                            },
                            columns: [
                                [
                                    { field: 'path', title: '路径', align: 'center', width: '30%', },
                                    { field: 'success', title: '是否成功', align: 'center', width: '10%', },
                                    { field: 'count', title: '计数', align: 'center', width: '10%', },
                                    { field: 'sum', title: '总耗时', align: 'center', width: '15%', },
                                    { field: 'min', title: '最快', align: 'center', width: '15%', },
                                    { field: 'max', title: '最慢', align: 'center', width: '15%', },
                                    { field: 'avg', title: '平均', align: 'center', width: '15%', },
                                ]],
                            onLoadSuccess: function () {
                                comFunc.cellShowTips(this, ['path', 'success', 'count', 'sum', 'min', 'max', 'avg']);
                            }
                        });
                    },
                    yes: function (index, layero) { //确定按钮的处理函数
                        layer.close(index);
                    },
                    btn2: function (index, layero) { //取消按钮后的处理函数
                        layer.close(index);
                    },
                });
            },
            setRecord: function () {
                this.lastSelCall = () => {
                    $('#' + search.vue.autoId).form('load', {
                        isNotRecord: false
                    });
                    delete dg.options().queryParams.isNotRecord;
                }
            },
            search_delay: 1,
            contrls: {
                $comOption: {
                    width: 170,
                    onSelect: () => search.searchFunc(search.search_delay),
                    onChange: () => search.searchFunc(search.search_delay),
                },
                查询内容: {
                    prompt: '我是代码设置的提示文本',
                    searcher: () => alert('执行搜索方法')
                },
                complete: {
                    precision: 17
                },
                orderField: {
                    width: 100,
                },
                isDesc: {
                    width: 100,
                },
                success: {
                    width: 100,
                },
                method: {
                    width: 100,
                },
                path: {},
                memo: {
                    width: 300,
                    onChange: (nv, ov) => {
                        //if (!ov) return;
                        //newModel.show();
                    },
                },
            },
            inited: false, //初始化状态
            RMenuInit() {
                //TODO: 有空看看这块代码怎么没有独立起来那个右键菜单
                comFunc.parseRMenu($('#sel_form1')[0],
                    [{
                        content: '清空',
                        click() {
                            let sd = search.getSearchData();
                            sd = comFunc.clone(sd);
                            for (let i in sd) {
                                if (i === 'memo') continue;
                                sd[i] = '';
                            }
                            search.vue.setVals(sd);
                        },
                    }]);
            },
            init: function () {
                this.RMenuInit();
                this.search_btn.init();
                $('#sel_form1').data('loadControls')(this.contrls);
                //this.inited = true;//标记为可以查询 // 交给 SearchLogInputDtoHelper 模块标记
                if ($.QueryString['uri']) {
                    this.contrls.path('setValue', $.QueryString['uri']);
                    setTimeout(() => {
                        $('#' + search.vue.autoId).form('load', {
                            isNotRecord: true
                        })
                        search.searchFunc(1); //如果附带了url 在执行一次查询
                        search.setRecord();
                        history.pushState({}, document.title,
                            location.href.replace(location.search, ''));
                        //修改url 避免刷新了还是那个查询条件 不过似乎会改变历史 后面可以再研究
                    }, 500);
                }
            },
            getSearchData() {
                let data = search.vue.getVals();
                data.orderField = search.contrls.orderField('getText');
                if (data.orderField === '全部') data.orderField = '';
                else alert('友情提示，order时请带参数查询，速度会更快');
                if (!data) return;
                return data;
            },
            searchFunc: function (delay = 1) {
                this.search_btn.change(delay);
                const exec = (delay) =>//每秒重新执行一次自己
                    comFunc.delayExecFunc('pageMain_searchFuncExec', () => {
                        this.searchFunc(--delay);
                    }, 1000);
                if (this.inited !== true) return exec(delay);
                if (delay > 0) return exec(delay);
                else clearTimeout(window["pageMain_searchFuncExec"]);
                let data = this.getSearchData();
                if (!data) return;
                delete data['id'];
                delete data['node'];
                dg('load', data);
            }
        };
        window['__search'] = search;
        //历史搜索记录模块
        let SearchLogInputDtoHelper = {
            list: [],
            len: 10,
            curMode: -1,
            getAll(call = null) {
                $.get('/WeblogApi/SearchLogInputDto/GetAll').then((data) => {
                    if (comFunc.handelError(data)) return;
                    if (Array.isArray(data) && data.length > 0) {
                        if (data.length < SearchLogInputDtoHelper.len) {
                            let arr = [];
                            for (var i = 0; i < SearchLogInputDtoHelper.len - data.length; i++)
                                arr.push(data[0]);
                            data = arr.concat(data);
                        }
                        SearchLogInputDtoHelper.list = data;
                        typeof (call) == "function" && call(data);
                        setTimeout(() => {
                            search.inited = true
                        }, 50);
                    } else {
                        search.inited = true;
                        $('#dtoSlider').slider('destroy');
                    }
                });
            },
            init() {
                let handerUrl = false;
                if (!$.QueryString['uri']) handerUrl = true;
                this.getAll((data) => {
                    let setp = 100 / SearchLogInputDtoHelper.len;
                    $('#dtoSlider').slider({
                        step: setp,
                        tipFormatter: function (value) {
                            if (!handerUrl) {
                                handerUrl = true;
                                return;
                            }
                            let mode = comFunc.toNum(value / setp, 0);
                            if (mode === 0) return;
                            if (SearchLogInputDtoHelper.curMode === mode) return;
                            SearchLogInputDtoHelper.curMode = mode;
                            let vals = comFunc.clone(data[mode - 1]);
                            vals.isNotRecord = true;
                            if (vals['node']) { //复杂查询
                                $('#' + search.vue.autoId).form('load', {
                                    memo: vals.memo
                                });
                                $('#__mode').switchbutton('check');
                                comFunc.delayExecFunc('pageMain_searchFuncExec', () => {},
                                    10); //取消之前的查询
                                setTimeout(() => {
                                    newModel.parseNode(vals['node']);
                                    newModel.search(true);
                                }, 150);
                            } else {
                                $('#__mode').switchbutton('uncheck');
                                search.vue.setVals(vals);
                                setTimeout(() => search.searchFunc(1), 100);//立即执行
                            }
                            search.setRecord();
                            layer.tips(`切换到了${(vals.memo || '倒数第') + '_' + (mode)}`,
                                $('#dtoSlider').data().slider.slider, {
                                    tips: [2, '#0FA6D8'], //还可配置颜色
                                });
                            return '';
                        }
                    });
                });
            }
        };
        let getFieldsByCookie = function () {
            return unescape(comFunc.getCookie('_weblog_fields'));
        };
        let dg = new euiControl({
            typeName: 'datagrid',
            el: $('#dg'),
            option: {
                url: '/WeblogApi/GetAllLog',
                fit: true,
                method: 'post',
                pageSize: 10,
                contentType: 'application/json; charset=utf-8',
                $Columns: [() => {
                    const changeColor = function (value, row, index) {
                        setTimeout(() => {
                            $('#dg').prevAll('div').find(
                                `tr.datagrid-row[datagrid-row-index='${index}']>td[field='${this.field}']`
                            )
                                .addClass('errorTd').css('background', backgrounds());
                        }, 500);
                    }
                    let result = comFunc.getColumnsByUrl(window, '/WebLogIndex/Get/log', null, {
                        success: {
                            width: 80,
                            title: 'success',
                            formatter: function (value, row, index) {
                                if (!value) {
                                    changeColor.apply(this, arguments);
                                }
                                return value;
                            }
                        },
                        date: {
                            width: 180,
                        },
                        path: {
                            width: 350,
                        },
                        message: {
                            width: 100,
                        },
                        data: {
                            width: 500,
                        },
                        isHttps: {
                            width: 50,
                            formatter: function (value, row, index) {
                                if (value) {
                                    changeColor.apply(this, arguments);
                                }
                                return value;
                            }
                        },
                        method: {
                            formatter: function (value, row, index) {
                                if (value !== 'GET') {
                                    changeColor.apply(this, arguments);
                                }
                                return value;
                            }
                        },
                        complete: {
                            formatter: function (value, row, index) {
                                if (value > 5) {
                                    changeColor.apply(this, arguments);
                                }
                                return value;
                            }
                        },
                        completed: {
                            formatter: function (value, row, index) {
                                if (!value) {
                                    changeColor.apply(this, arguments);
                                }
                                return value;
                            }
                        },
                        referer: {
                            width: 350,
                        },
                    });
                    result.forEach(el => el.editor = el._editor); //都设置成可编辑
                    result = [{
                        field: '_',
                        title: '重发',
                        align: "center",
                        width: 100,
                        formatter: function (v, r, i) {
                            r['method'] === 'POST' || changeColor.apply(this, arguments);
                            return "<a href='JavaScript:void(0);' class='btn btn-xs' title='原封不动重发' onclick='dg(\"sendByRow\", " +
                                i + ")'><i class='fa fa-thumbs-up'></i></a>" +
                                (
                                    r['method'] === 'POST' ? '' :
                                        "<a href='JavaScript:void(0);' class='btn btn-xs' title='从浏览器打开(要手动按F5)' onclick='dg(\"openWebByRow\", " +
                                        i + ")'><i class='fa fa-window-restore'></i></a>"
                                );
                        }
                    }].concat(result);
                    const historys = getFieldsByCookie().split(',');
                    const getIdx = (f) => {
                        let result = -1;
                        return (result = historys.indexOf(f)) == -1 ? result.length : result;
                    }
                    result.sort((a, b) => getIdx(a.field) - getIdx(b.field))
                    return result;
                }],
                $EditOptions: {
                    查询内容: {
                        searcher: function (value, name) {
                            comFunc.alert(value);
                        }
                    },
                    普通的字符串: {
                        onChange: function (nv) {
                            comFunc.alert(nv);
                        }
                    },
                    下拉框: {
                        onSelect: function () { }
                    }
                },
                _onLoadSuccess(data) {
                    typeof (search.lastSelCall) === 'function' && search.lastSelCall();
                    search.lastSelCall = undefined;
                    let datagridData = $(this).data('datagrid'),
                        cols = datagridData.options.columns[0].map(r => new Object({
                            field: r.field, title: r.title
                        }));
                    let fs = cols.map(r => r.filed); //可以在创建的生命周期后面补上扩展的判断 然后加入cellShowTips 但是会带来的是，扩展写法支持，原生不支持
                    comFunc.cellShowTips('#dg', fs, true);
                    comFunc.unRMenu && comFunc.unRMenu(this);
                    setTimeout(() =>
                        comFunc.parseRMenu($(this).data('datagrid').panel[0],
                            comFunc.getElFunc(this).getRMenuData(cols), (e) => {
                        }), 1);
                }
            },
            on: {
                beforeLoad(param) {
                    if (document.readyState !== 'complete') { //文档没准备好
                        $(() => search.searchFunc(1));
                        return false;
                    }
                    return true;
                },
                clickRow: function (index, row) {
                    let _row = comFunc.clone(row);
                    $.get('/WeblogApi/SqlLog/GetAll', {
                        id: row['id']
                    })
                        .then((data) => {
                            if (comFunc.handelError(data));
                            else if (Array.isArray(data) && data.length > 0) {
                                _row._sqls = data.map(r => {
                                    console.warn('--' + r.sql.replace(/@__ef_filter__IsSoftDeleteFilterEnabled_\d+/g, '1'));
                                    r.sql = r.sql.replace('↵', '\n');
                                    return r;
                                });
                            } else _row._sqls = '无';
                            showTxt(_row);
                        });
                },
                clickCell: function (index, field, value) {
                    $(`td[field='${'_'}']`).find('div').find('a').removeClass('fa-spin');
                    let td = $(`tr.datagrid-row[datagrid-row-index='${index}']>td[field='${'_'}']`);
                    td.find('div').find('a').eq(0).addClass('fa-spin'); //添加样式 似乎每次刷新点击都会更新内容 所以不用写移除旋转样式的代码
                    showCellTxt(field, value);
                    var param = {
                        index: index,
                        field: field
                    };
                    $(this).datagrid('editCell', param);
                },
                stopDragColumn: function (field) {
                    setTimeout(() => {
                        const fields = dg.getColumnFields(true).concat(dg
                            .getColumnFields()); // 获取解冻列
                        dg.setFieldsByCookie(fields.join(','));
                    }, 100);
                },
            },
            methods: {
                getFieldsByCookie: getFieldsByCookie,
                setFieldsByCookie: function (fields) {
                    comFunc.setCookie('_weblog_fields', escape(fields));
                },
                getTools: function (e) {
                    let res = comFunc.getdgToolByEl(e.event.path[0]);
                    if (!res || isNaN(res.index)) return undefined;
                    return res;
                },
                getSingleLog: function (row, field) {
                    let url = location.origin + `/WeblogApi/GetSingleLog?id=${row.id}&field=${field || ''}`;
                    url && window.open(url);
                },
                getRMenuData: function (cols) {
                    return [
                        {
                            text: '查看行JSON', click: (e) => {
                                let t = this.getTools(e);
                                if (!t || !t.row) return;
                                this.getSingleLog(t.row);
                            }
                        },
                        {
                            text: '查看单元格JSON',
                            click: (e) => {
                                let t = this.getTools(e);
                                if (!t || !t.row || !t.field) return;
                                this.getSingleLog(t.row, t.field);
                            },
                            childrens: cols.map(r => new Object({
                                text: r.title,
                                field: r.field,
                                click: (e) => {
                                    let t = this.getTools(e);
                                    if (!t || !t.row) return;
                                    this.getSingleLog(t.row, e.per.field);
                                    return false;
                                }
                            }))
                        },
                        {
                            text: '新窗口打开', click: (e) => {
                                let t = this.getTools(e);
                                if (!t || !t.row || !t.row.method) return;
                                if (t.row.method !== 'GET') return t.tips('只有POST方式才可以调用');
                                window.open((t.row.isHttps ? 'https://' : 'http://')
                                    + t.row.path + t.row.query);
                                //debugger
                            },
                            childrens: [{
                                text: '当前界面窗口打开',
                                click: (e) => {
                                    let t = this.getTools(e);
                                    if (!t || !t.row) return;
                                    this.openWebByRow(t.index);
                                    return false;
                                }
                            }
                            ]
                        },
                        {
                            text: '原封不动重发',
                            click: (e) => {
                                let t = this.getTools(e);
                                if (!t || !t.row) return;
                                this.sendByRow(t.index);
                                return false;
                            }
                        },
                        {
                            text: '修改配置',
                            click: () => dialog.open()
                        },
                        {
                            text: '打开Swagger',
                            click: openSwagger
                        },
                        {
                            text: '修改监听配置',
                            click: () => LogPath.open()
                        },
                        {
                            text: '查看系统日志',
                            click: () => SysLog.open()
                        },
                        {
                            text: 'api分析',
                            click: __search.showAnalyze
                        }
                    ];
                },
                _getRow: function (idx, callBack) {
                    if (typeof (callBack) !== 'function') return;
                    let row = this.getRows()[idx];
                    row = comFunc.clone(row);
                    let getRoot = (_url) =>
                        _url.replace('http://', '').replace('https://', '').split('/')[0];
                    let curRoot, rowRoot;
                    let rootEq = (curRoot = getRoot(window.location.href)) === (rowRoot = getRoot(row
                        .path));
                    row._root = rowRoot;
                    if (rowRoot !== curRoot)
                        $.messager.confirm('提示', `当前url【${rowRoot}】与站点前缀【${curRoot}】不符，是否替换成站点前缀再重发！`, (
                            r) => {
                            if (r) {
                                row.path = row.path.replace(rowRoot, curRoot);
                                row._root = curRoot;
                            }
                            callBack.call(this, row);
                        });
                    else callBack.call(this, row);
                },
                openWebByRow: function (idx) {
                    this._getRow(idx, function (row) {
                        let url = row.path + row.query;
                        if (url.toLowerCase().indexOf("http") != 0) url = (row.isHttps ?
                            'https://' : 'http://') + url;
                        layer.open({
                            type: 2,
                            title: (row.path.replace(row['_root'] || '', '') + row.query),
                            area: ['90%', '90%'],
                            shade: 0,
                            shadeClose: true,
                            maxmin: true,
                            content: url //这里content是一个URL，如果你不想让iframe出现滚动条，你还可以content: ['http://sentsin.com', 'no']
                        });
                    });
                },
                sendByRow: function (idx, isEdit) {
                    let row = this.getRows()[idx];
                    const send = () => {
                        let data = {};
                        if (row.body) data = row.body;
                        let url = row.path; //.replace(/(\d.+?\.)+(\d.+?\:\d+)/, '');
                        if (url.toLowerCase().indexOf("http") != 0) url = (row.isHttps ? 'https://' :
                            'http://') + url;
                        if (row.query) url = url + row.query;
                        $.messager.progress();
                        $.ajax({
                            url: url,
                            type: row.method,
                            contentType: row.contentType,
                            data: data,
                            success: function (data) {
                                $.messager.progress('close')
                                alert('【结果】已输出到文本框！');
                                showCellTxt('重发结果', data);
                            },
                            error: function () {
                                $.messager.progress('close')
                                alert('【错误】已输出到文本框，详细请看控制台！');
                                showCellTxt('发生异常', arguments);
                                console.error(arguments);
                            }
                        });
                    };
                    if (isEdit) {
                        $.messager.prompt('提示', '请输入您要发送请求的url（数字ip会自动变为localhost）。当前url    ' + row.path, (
                            txt) => {
                            if (!txt) {
                                alert('未接收到,将直接转换为localhost调用！');
                                txt = row.path;
                            }
                            txt = txt.replace(/(\d.+?\.)+(\d.+?)/, 'localhost'); //改成发本地
                            row.path = txt;
                            this.refreshRow(idx);
                            send();
                        })
                    } else {
                        this._getRow(idx, function (_row) {
                            row = _row;
                            send();
                        });
                    }
                }
            }
        })
        $(() => {
            dg('columnMoving');
        });
        let dialog = {
            el: $('#dialog-changeConfig'),
            dialog: comFunc.getElFunc($('#dialog-changeConfig')),
            open: function () {
                $.get('/weblogapi/GetConfig', (data) => {
                    if (comFunc.handelError(data)) return;
                    dialog.lastData = data;
                    dialog.el.data('setVals')(data);
                });
                this.dialog('open');
            },
            save: function (data, close) {
                $.get('/weblogapi/SetConfig', data, (data) => {
                    if (comFunc.handelError(data)) return;
                    comFunc.alert('操作成功');
                    dialog.lastData = data;
                    dialog.el.data('setVals')(data);
                    close();
                });
            },
            contrls: {
                $comOption: {
                    width: 170,
                    min: 0.5,
                }
            },
            init() {
                this.el.data('loadControls')(this.contrls);
            },
        };

        $(() => {
            search.init();
            newModel.init();
            SearchLogInputDtoHelper.init();
            dialog.init();
            LogPath.init();
            SysLog.init();
        });
        let showTxt = (data) => JsonRow.resetAndRefresh(data);
        let showCellTxt = (field, value) => {
            let obj = {}
            obj[field] = value;
            if (field === 'query' && value)
                obj['queryObj'] =
                value.replace(/^\?/, '').split('&')
                .reduce((acc, val, i) => {
                    let _p = val.split('=');
                    if (_p.length > 1)
                        acc[_p[0]] = _p[1];
                    return acc;
                }, {});

            JsonCell.resetAndRefresh(obj, 3);
            $('#cellText').textbox('setValue', typeof (value) == 'string' ? value : JSON.stringify(value));
        }
        const LogPath = { //查询做起来
            el: $('#logPathDialog'),
            vue: $('#logPathDialog').data('vue'),
            eFunc: comFunc.getElFunc($('#logPathDialog')),
            open() {
                LogPath.dg('reload');
                this.eFunc('open');
            },
            AddOrSet(PathJoins, IsEnable, call) {
                $.get('/WeblogApi/SqlLogPath/AddOrSet', {
                        IsEnable: IsEnable,
                        PathJoins: PathJoins
                    })
                    .then((msg) => {
                        alert(msg);
                        typeof (call) === 'function' && call();
                    });
            },
            add() {
                $.messager.prompt('提示信息', '请输入监听路由（可用逗号分隔）：', (r) =>
                    r && LogPath.AddOrSet(r, true, () => LogPath.dg('load', {}))
                );
            },
            saveCall: (data, close) => {
                console.log(data);
                close();
            },
            contrls: {
                $comOption: {
                    width: 170,
                    onChange: () => LogPath.dg.load({})
                }
            },
            init() {
                this.el.data('loadControls')(this.contrls);
            },
            dg: new euiControl({
                typeName: 'datagrid',
                el: $('#logPathDg'),
                option: {
                    url: '/WeblogApi/SqlLogPath/GetAll',
                    fit: false,
                    method: 'get',
                    pageSize: 10,
                    height: 600,
                    $Columns: [
                        [{
                            field: '_',
                            title: '_',
                            align: "center",
                            width: 100,
                            formatter: function (v, r, i) {
                                return `<a href='JavaScript:void(0);' class='btn btn-xs' title='删除' onclick='LogPath.dg("Del", ${i})'><i class='fa fa-trash'></i></a>
                    <a href='JavaScript:void(0);' class='btn btn-xs' title='启用/禁用' onclick='LogPath.dg("Disable", ${i})'><i class='fa fa-pencil'></i></a>
                                    `;
                            }
                        }].concat(comFunc.getColumnsByUrl(window, '/WebLogIndex/Get/logPath', null, {
                            path: {
                                width: 220,
                            }
                        }))
                    ]
                },
                on: {
                    beforeLoad(param) {
                        if (document.readyState !== 'complete') { //文档没准备好
                            return false;
                        }
                        let data = LogPath.el.data('getVals')();
                        for (let i in data) param[i] = data[i];
                        return true;
                    },
                },
                methods: {
                    Add: () => LogPath.add(),
                    Disable(idx) {
                        let row = this.getRows()[idx];
                        row = comFunc.clone(row);
                        let paths = row.path;
                        if (!Array.isArray(paths)) paths = [paths];
                        LogPath.AddOrSet(paths.join(','), !row.isEnable, () => LogPath.dg.load({}));
                    },
                    Del(idx) {
                        let row = this.getRows()[idx];
                        row = comFunc.clone(row);
                        let paths = row.path;
                        if (!Array.isArray(paths)) paths = [paths];
                        $.get('/WeblogApi/SqlLogPath/Del', {
                            PathJoins: paths.join(',')
                        }).then((msg) => {
                            alert(msg);
                            LogPath.dg.load({});
                        });
                    },
                }
            })
        }
        let deleteLog = () => {
            $.post('/WeblogApi/Delete/TryDelete');
        }
        let consoleHistorys = () => $.get('/WeblogApi/GetSearchLogDtoHistorys', (data) => {
            console.log(data);
        });
        let loadMail = () => {
            if (!layer || !$) return;
            window.sendMail = () => {
                layer && layer.open({ //打开layer弹出框
                    offset: '75%', //距离顶上的距离
                    type: 1, //类型
                    title: "邮件反馈" + getRandomTxt(), //定义标题
                    content: `对于这个扩展系列如果有任意效率上的意见,欢迎点击发送
                        <br/><textarea style="height:100px;width:350px;" placeholder="${getRandomTxt()}" id="__body"/>`, //输出的字符串，定义弹出框的html页面
                    btn: ['发送', '取消'], //按钮
                    success(){
                        $("#__body").focus();
                    },
                    yes: function (index, layero) { //确定按钮的处理函数
                        let body = $("#__body").val(); //根据id取数据
                        if (!body || !body.trim()) return alert('没有内容，请点击取消');
                        $.post('/WeblogApi/Email/SendMail', {
                            body: body,
                            pwd: '@6947',
                        }).then(data => {
                            if (comFunc.handelError(data)) return;
                            typeof (data) !== 'string' || alert(data);
                        });
                        layer.close(index);
                    },
                    btn2: function (index, layero) { //取消按钮后的处理函数
                        layer.close(index);
                    },
                });
            }
            layer && $(() => {
                let showTxts = [`(〃'▽'〃)`, `( • ̀ω•́ )✧`, `( • ̀ω•́ )✧`, `(〃´-ω･) `
                , `「(°ヘ°)`, `( σ_σ)`, `(｀ε´)|`
                , `o((=ﾟ♀ﾟ=))o`, `o((=^T^=))o`
                , `ヾ(✿ﾟ▽ﾟ)ノ`, `ヾ(◍°∇°◍)ﾉﾞ`];
                let getRandomTxt = () => showTxts[parseInt(showTxts.length * Math.random() + '')];
                window.showTxts = showTxts;
                window.getRandomTxt = getRandomTxt;
                $('body').append(`
                    <div id="__mailDiv" style="position: fixed;bottom:35px;right:0px;height:auto;overflow:auto;">
                        <a id="__mailBtn" href="javascript:void(0)" onclick="sendMail()">${getRandomTxt()}</a>
                    </div>`);
                });
                let touchMsg = `一个平平无奇的意见反馈按钮~~~~`;
                setTimeout(() => {
                    $('#__mailDiv>#__mailBtn').hover(function(e,b,c){
                        layer.tips(touchMsg + getRandomTxt(), '#__mailDiv>#__mailBtn', {
                            //tipsMore: true,
                            tips: [4, '#0FA6D8'], //还可配置颜色
                        });
                    });
                }, 200);
        }
        loadMail();
        console.warn('可以使用 deleteLog 方法清理日志;consoleHistorys可以查询请求日志');
        const SysLog = {
            el: $('#logDialog'),
            vue: $('#logDialog').data('vue'),
            eFunc: comFunc.getElFunc($('#logDialog')),
            contrls: {
                $comOption: {
                    width: 170,
                    onChange: () => SysLog.dg.load({})
                }
            },
            init() {
                this.eFunc({
                    width: 1000,
                    height: 500,
                });
                this.el.data('loadControls')(this.contrls);
            },
            open() {
                SysLog.dg.reload();
                this.eFunc('open');//这个方法在window open里面 无法透过dialog使用到
                //this.eFunc.open();
            },
            dg: new euiControl({
                typeName: 'datagrid',
                el: $('#SysLogDG'),
                option: {
                    url: '/WeblogApi/SysLog/GetAll',
                    fit: false,
                    method: 'get',
                    pageSize: 10,
                    height: 600,
                    $Columns: [(() => {
                        let result = comFunc.getColumnsByUrl(window, '/WebLogIndex/Get/sysLog',
                            null, {
                                msg: {
                                    width: 550,
                                },
                                date: {
                                    width: 220
                                }
                            });
                        result.forEach(el => el.editor = el._editor); //都设置成可编辑
                        return result;
                    })()]
                },
                on: {
                    beforeLoad(param) {
                        if (document.readyState !== 'complete') { //文档没准备好
                            return false;
                        }
                        let data = SysLog.el.data('getVals')();
                        for (let i in data) param[i] = data[i];
                        return true;
                    },
                },
                methods: {}
            })
        };
        let openSwaggerNum = 0;
        const openSwagger = () => {
            layer.open({
                type: 2,
                title: 'Swagger' + (++openSwaggerNum),
                area: ['90%', '85%'],
                shade: 0,
                shadeClose: true,
                maxmin: true,
                content: `http://${location.host}/swagger/index.html`,
                end() {
                    window.iframeWinJump = undefined
                },
                success(layero, index) {
                    let iframeWin = window['layui-layer-iframe' + index];
                    window.iframeWinJump = (OpenUrl) => iframeWin.location.href = OpenUrl;
                },
                cancel() {
                    //alert('cancel')
                }
            });
        };

        let searchMixin = { //搜索 - data改变监听
            data: function () { //mixin模式的data需要是函数
                return {
                    //查询相关的
                    filter: '', //如果不为string类型 则不显示查询框
                    isInFilter: false, //在查询状态中（因为查询会过滤对象）
                    hasOldDatas: false, //
                    oldDatas: null, //查询之前的对象 在filter归零时还原数据用的
                    placeholder: '', //默认提示文本
                    isOr: false, //true 两个空格间是或者关系 false 两个空格间是并且关系
                    DelayfilterTime: 500, //毫秒

                    changeDataPaths: [], //改变数据源的集合
                    changeDataPathStr: '', //当前路径
                    changeDataPathIdx: undefined, //激活的路径 空的时候就是一直到最后一个
                }
            },
            watch: {
                filter: {
                    handler(newVal, oldVal) {
                        this.DelayfilterData && this.DelayfilterData(newVal);
                    },
                    deep: true,
                    immediate: false,
                },
                isOr: {
                    handler(newVal, oldVal) {
                        this.DelayfilterData && this.DelayfilterData(this.filter);
                    },
                    deep: true,
                    immediate: false,
                },
                changeDataPaths: {
                    handler(newVal, oldVal) {
                        this.changeDataPathStr = this.getDataByChangeDataPath();
                    },
                    deep: true,
                },
                changeDataPathIdx: {
                    handler(newVal, oldVal) {
                        this.changeDataPathStr = this.getDataByChangeDataPath();
                    },
                    deep: true,
                },
            },
            created: function () {
                /*
                 * 会先进入mixin 再进入原本的create
                 * 会把这个mixin的方法也给到组件上去 （组件里面有代码： mixins: [myMixin],）
                 * this 对象好像已经是使用mixin组件的对象了
                 */
                //debugger
            },
            methods: {
                /**
                 * 搜索元素是的匹配
                 * @param {*} str
                 * @param {*} findS
                 */
                findStr(str, findS) { //匹配字符串 且支持缩写 成功返回true
                    if (typeof (findS) !== 'string') return false;
                    if (str.trim() === findS.trim()) return true;
                    const findFunc = (_finds) => {
                        const fs = eval(`/${_finds}/i`);
                        let _match = str.match(fs);
                        if (!_match) { //连续的大写匹配 支持驼峰
                            const allCapital = (str.match(/[A-Z]/g) || ['']).join('')
                            const first = (str.match(/^[a-z]/) || [''])[0];
                            _match = (first + allCapital).match(fs);
                        }
                        return _match;
                    }
                    let isFind = findFunc(findS); //匹配原始的
                    findS = findS.split(' ');
                    return isFind || findS[this.isOr ? 'some' : 'every'](s => findFunc(s
                        .trim())); //原始的匹配不出来 就匹配空格分隔的
                },
                setOldDatas() {
                    if (!this.oldDatas) {
                        this.oldDatas = {};
                        for (const title in this['datas']) { //对第一层进行复制
                            this.oldDatas[title] = this['datas'][title];
                        }
                    }
                    this.hasOldDatas = true;
                },
                getOldDatas() {
                    let setData = {}
                    for (const pn in (this.oldDatas || {}))
                        setData[pn] = this.oldDatas[pn]
                    return setData;
                },
                /**
                 * 重新设置数据回去
                 */
                resetOldDatas(type = '') {
                    let _setData = this.getOldDatas();
                    if (Object.keys(_setData).length > 0) {
                        if (type === 'filter' && this.changeDataPaths.length > 0) {
                            //如果是从查询还原的数据 并且有跳转过数据
                            _setData = this.getDataByChangeDataPath(_setData);
                            this.refresh(_setData, 1, false);
                            return;
                        } else this.refresh(_setData, 1, false);
                    }
                    while (this.changeDataPaths.pop());
                    this.oldDatas = null;
                    this.filter = '';
                    this.hasOldDatas = false;
                    this.changeDataPathStr = '';
                },
                getDataByChangeDataPath(data) {
                    let _setData = data,
                        path = '';
                    this.changeDataPaths.forEach((s, idx) => {
                        //超过了当前所在的层数的话 直接返回
                        if (this.changeDataPathIdx !== undefined && idx > this
                            .changeDataPathIdx) return;
                        path += s;
                    }); //深入记录的层数
                    if (data)
                        eval(`_setData = _setData${path}`);
                    else return path;
                    return _setData;
                },
                pathNext() { //前进
                    if (this.changeDataPathIdx === undefined) return;
                    this.changeDataPathIdx += 1;
                    this.resetOldDatas('filter');
                },
                pathLast() { //后退
                    if (this.changeDataPathIdx === undefined)
                        this.changeDataPathIdx = this.changeDataPaths.length - 1;
                    this.changeDataPathIdx -= 1;
                    this.resetOldDatas('filter');
                },
                DelayfilterData(val, DelayfilterTime = undefined) {
                    if (typeof (this.filterData) === 'function')
                        comFunc.delayExecFunc('__json_filterChange', () =>
                            setTimeout(() => {
                                val && this.tipMsg('查询中');
                                setTimeout(() => {
                                    this.filterData(val);
                                }, 20);
                            }, DelayfilterTime === undefined ? this.DelayfilterTime : DelayfilterTime));
                },
                filterData(val) {
                    if (this.notSet) {
                        this.tipMsg('数据未渲染，还不能搜索！');
                        return;
                    }
                    if (val && val.trim()) {
                        val = val.trim();
                        this.setOldDatas();
                        let c = 0;
                        let hasOldData = false;
                        const _find = (obj, findVal) => {
                            c++;
                            let result = undefined;
                            if (Array.isArray(obj)) {
                                result = [];
                                obj.forEach((o, idx) => {
                                    let rv = _find(o, findVal);
                                    if (rv) {
                                        rv[`原始数据_[${idx}]`] = o;
                                        result.push(rv); //rv
                                        hasOldData = true;
                                    }
                                });
                                if (result.length === 0) return undefined;
                                result = result.sort((a, b) => Object.keys(b).length - Object.keys(a).length);
                            } else if (typeof (obj) === 'object') {
                                result = {};
                                for (const key in obj) {
                                    if (this.findStr(key, findVal)) { //从key上面找 key有值就显示
                                        result[key] = obj[key];
                                    } else { //在值里面找
                                        let vResult = _find(obj[key], findVal);
                                        if (!vResult) continue; //值里面没有 就不显示
                                        result[key] = vResult;
                                    }
                                }
                                if (Object.keys(result).length === 0) result = undefined; //啥也没找到
                            } else {
                                if (this.findStr(obj.toString(), findVal)) result = obj;
                            };
                            return result;
                        };
                        let _setData = this.getDataByChangeDataPath(this.getOldDatas()); //获得经过这个深度的对象
                        this.refresh(_find(_setData, val), undefined, false);
                        console.log(`---------------------${c}`); //运行find次数
                        this.tipMsg('查询已完成');
                        let tagDeep = this.maxDeep - (hasOldData ? 1 : 0);
                        [0, tagDeep].forEach((_deep, idx) =>
                            setTimeout(() => this.deep = _deep, idx * 10))
                        this.isInFilter = true;
                        //做查询操作
                    } else if (this.oldDatas) { //还原数据
                        this.resetOldDatas('filter');
                        this.isInFilter = false;
                    }
                },
                resetAndRefresh() { //还原数据并设置数据
                    this.$children[0].visible = false;
                    const oldFilter = this.filter;
                    this.oldDatas = {};
                    this.resetOldDatas();
                    this.filter = oldFilter;
                    this.refresh.apply(this, arguments);
                },
                changeData(el) { //由于查询会 使用oldDatas作为查询的数据源 尽管这里切换了 却还是无效
                    //默认双击方法 把双击的key作为主数据
                    if (el.classList.contains('json-value')) { //对于value的表现是复制
                        comFunc.copyTxt($(el).text().trim().match('"(.+?)"')[1]);
                        return;
                    }
                    let curEl = $(el),
                        keyArr = [],
                        arrIdx = undefined;
                    const getCurWrap = (_el) => {
                        return $(_el).parents('.json-body:eq(0)').parent('.content-wrap:eq(0)');
                    };
                    const pushByEl = (_el) => {
                        let match = $(_el).text().match(/^\"(.+?)\"\:\s?$/);
                        if (match)
                            keyArr.push(`['${match[1]}']`);
                    }
                    let isFirst = true;
                    while ($(curEl).length > 0) {
                        let match = '';
                        if (isFirst) pushByEl(curEl);
                        let _curEl = getCurWrap(curEl).find('.json-key').eq(0);
                        if (getCurWrap(curEl)[0] === getCurWrap(_curEl)[0]) { //找到的元素和当前在一级别
                            if (curEl.parents('.content-wrap').length === 2) break; //最上面一级了
                            let bigs = getCurWrap(_curEl).parents('.json-body>.json-view-container').eq(
                                0).parent().children('.json-view-container');
                            bigs.each((idx, el) => {
                                if ($(el).has(_curEl).length > 0)
                                    arrIdx = idx; //这种情况当成数组处理
                            });
                            if (arrIdx !== undefined)
                                keyArr.push(`[${arrIdx}]`);
                            curEl = bigs.eq(0).parents('.content-wrap').eq(0).find('.json-key').eq(0);
                            if (curEl[0] === _curEl[0]) //再往上一级
                                curEl = bigs.eq(0).parents('.content-wrap').eq(1).find('.json-key').eq(
                                    0);
                            pushByEl(curEl);
                        } else {
                            curEl = _curEl;
                            pushByEl(curEl);
                        }
                        isFirst = false;
                    }
                    keyArr.reverse();
                    let _data = '',
                        _this = this,
                        curDataStr = '';
                    while ((typeof (_data) !== 'object' || !_data) && keyArr.length > 0) {
                        eval(`_data = _this.datas${curDataStr = (keyArr.join(''))}`);
                        keyArr.pop();
                    }
                    curDataStr && layer.confirm(`切换数据源到${curDataStr}?`, {
                        icon: 3,
                        title: '是否切换'
                    }, (index) => {
                        layer.close(index);
                        if (Object.keys(this.getOldDatas()).length === 0)
                            this.setOldDatas();
                        let olds = this.getDataByChangeDataPath();
                        while (this.changeDataPaths.pop());
                        this.changeDataPaths.push(olds);
                        this.changeDataPaths.push(curDataStr);
                        this.changeDataPathIdx = this.changeDataPaths.length - 1;
                        this.refresh(_data); //备份原来的数据 然后还原数据
                        this.tipMsg('切换完成');
                    });
                },
            }
        }
        const CreteJsonV = (elId, initDatas = {},
            KEYClick = undefined, VALUEClick = undefined,
            DBKEYClick = undefined, DBVALUEClick = undefined,
            GetElTipCall = undefined) => {
            if (!document.getElementById(elId)) return;
            if (typeof (initDatas) === 'object') {
                let _datas = {};
                for (const i in initDatas) {
                    _datas[i] = initDatas[i];
                } //克隆一下 避免数据公用 影响外部对象
                initDatas = _datas;
            }
            //代码太多了 考虑分到不同功能区
            return new Vue({
                el: '#' + elId,
                data: {
                    theme: 'one-dark', //可选主题样式,可选值为one-dark、vs-code，不选时为默认的白色主题
                    closed: false,
                    deep: 1, //默认展开的深度
                    maxDeep: 1, //数据的最大深度 赋值时会自动更新
                    fontSize: 14,
                    lineHeight: 24,
                    datas: initDatas,
                    notSet: true, //初始状态 没执行赋值

                    isBindClick: true, //给元素绑定点击事件
                    //查询相关的
                    filter: '', //如果不为string类型 则不显示查询框
                    isInFilter: false, //在查询状态中（因为查询会过滤对象）
                    hasOldDatas: false, //
                    oldDatas: null, //查询之前的对象 在filter归零时还原数据用的
                    placeholder: '', //默认提示文本
                    isOr: false, //true 两个空格间是或者关系 false 两个空格间是并且关系
                    DelayfilterTime: 500, //毫秒

                    fixedTool: true, //工具栏 定位使用fixed false的时候使用默认值

                    allowDBChangeData: true, //允许双击切换数据源（深入数据源）
                    changeDataPaths: [], //改变数据源的集合
                    changeDataPathStr: '', //当前路径
                    changeDataPathIdx: undefined, //激活的路径 空的时候就是一直到最后一个
                },
                watch: {
                    filter: {
                        handler(newVal, oldVal) {
                            this.DelayfilterData && this.DelayfilterData(newVal);
                        },
                        deep: true,
                        immediate: false,
                    },
                    isOr: {
                        handler(newVal, oldVal) {
                            this.DelayfilterData && this.DelayfilterData(this.filter);
                        },
                        deep: true,
                        immediate: false,
                    },
                    changeDataPaths: {
                        handler(newVal, oldVal) {
                            this.changeDataPathStr = this.getDataByChangeDataPath();
                        },
                        deep: true,
                    },
                    changeDataPathIdx: {
                        handler(newVal, oldVal) {
                            this.changeDataPathStr = this.getDataByChangeDataPath();
                        },
                        deep: true,
                    },
                },
                components: {
                    jsonView: window['vue-json-view'].default
                },
                template: ` <div id='${elId}'>
                <div style="position:absolute;z-index: 1000;bottom:2%;right:2px;color:#7bbfea;cursor: pointer;">
                    <input tips="折叠json" type="checkbox" @change="jsonClosedCheckChange" />
                    <br/>
                    <input tips="隐藏搜索框" type="checkbox" @change="toolShowCheckChange" />
                </div>
                <div class="tool" style="position:absolute;z-index: 999;right:0;color:#7bbfea;font-size: 16px;width: 200px;cursor: pointer;">
                    <input id="selectInput" tips="查询json内部" type="text" v-if="typeof(filter)==='string'" :placeholder="placeholder" v-model="filter" style="width:90%" />
                    <br/>
                    展开深度
                    <select class="deepSelect" @change="selectDeepChange">
                        <option v-for="idx in maxDeep" :value="idx">{{ idx }}</option>
                    </select>
                    或运算
                    <input type="checkbox" v-model="isOr">
                    <br/>
                    <a v-show="hasOldDatas" @click="resetOldDatas">还原数据</a>
                    <a tips="后退" v-show="changeDataPaths.length>0&&changeDataPathIdx>-1" @click="pathLast">👈</a>
                    <a tips="前进" v-show="changeDataPaths.length>0&&changeDataPathIdx<changeDataPaths.length-1" @click="pathNext">👉</a>
                    <br/>
                    <span>{{changeDataPathStr}}</span>
                </div>
                <json-view :data="datas" :deep="deep" :closed="closed" :font-size="fontSize" :theme="theme" :line-height="lineHeight"/>
            </div>`,
                methods: {
                    tipMsg(msg, domSelectStr = '#' + elId) {
                        if (layer) {
                            let arr = []
                            if (typeof (msg) === 'string') arr.push(msg);
                            else if (Array.isArray(msg)) arr = msg;
                            else return;
                            let idxs = arr.map(s =>
                                layer.tips(s, domSelectStr, {
                                    //tipsMore: true,
                                    tips: [4, '#0FA6D8'], //还可配置颜色
                                })
                            );
                            $(domSelectStr).mouseleave(() => //鼠标离开时 销毁
                                setTimeout(() => idxs.forEach(i => layer.close(i)), 300));
                            return idxs.length === 1 ? idxs[0] : idxs;
                        } else alert(msg);
                    },
                    /**
                     * 搜索元素是的匹配
                     * @param {*} str
                     * @param {*} findS
                     */
                    findStr(str, findS) { //匹配字符串 且支持缩写 成功返回true
                        if (typeof (findS) !== 'string') return false;
                        if (str.trim() === findS.trim()) return true;
                        let keyArr = ['.', '(', '|'];
                        const findFunc = (_finds) => {
                            let fs = _finds;
                            try {
                                //keyArr.forEach(k => fs = fs.replace(eval(`/\\${k}/g`), '\\' + k));
                                fs = eval(`/${fs}/i`);
                                let _match = str.match(fs);
                                if (!_match) { //连续的大写匹配 支持驼峰
                                    const allCapital = (str.match(/[A-Z]/g) || ['']).join('')
                                    const first = (str.match(/^[a-z]/) || [''])[0];
                                    _match = (first + allCapital).match(fs);
                                }
                                return _match;
                            } catch (e) {
                                debugger
                                console.log('异常了');
                                return str == _finds;
                            }
                        }
                        let isFind = findFunc(findS); //匹配原始的
                        findS = findS.split(' ');
                        return isFind || findS[this.isOr ? 'some' : 'every'](s => findFunc(s
                            .trim())); //原始的匹配不出来 就匹配空格分隔的
                    },
                    setOldDatas() {
                        if (!this.oldDatas) {
                            this.oldDatas = {};
                            for (const title in this['datas']) { //对第一层进行复制
                                this.oldDatas[title] = this['datas'][title];
                            }
                        }
                        this.hasOldDatas = true;
                    },
                    getOldDatas() {
                        let setData = {}
                        for (const pn in (this.oldDatas || {}))
                            setData[pn] = this.oldDatas[pn]
                        return setData;
                    },
                    /**
                     * 重新设置数据回去
                     */
                    resetOldDatas(type = '') {
                        let _setData = this.getOldDatas();
                        if (Object.keys(_setData).length > 0) {
                            if (type === 'filter' && this.changeDataPaths.length > 0) {
                                //如果是从查询还原的数据 并且有跳转过数据
                                _setData = this.getDataByChangeDataPath(_setData);
                                this.refresh(_setData, 1, false);
                                return;
                            } else this.refresh(_setData, 1, false);
                        }
                        while (this.changeDataPaths.pop());
                        this.oldDatas = null;
                        this.filter = '';
                        this.hasOldDatas = false;
                        this.changeDataPathStr = '';
                    },
                    getDataByChangeDataPath(data) {
                        let _setData = data,
                            path = '';
                        this.changeDataPaths.forEach((s, idx) => {
                            //超过了当前所在的层数的话 直接返回
                            if (this.changeDataPathIdx !== undefined && idx > this
                                .changeDataPathIdx) return;
                            path += s;
                        }); //深入记录的层数
                        if (data)
                            eval(`_setData = _setData${path}`);
                        else return path;
                        return _setData;
                    },
                    pathNext() { //前进
                        if (this.changeDataPathIdx === undefined) return;
                        this.changeDataPathIdx += 1;
                        this.resetOldDatas('filter');
                    },
                    pathLast() { //后退
                        if (this.changeDataPathIdx === undefined)
                            this.changeDataPathIdx = this.changeDataPaths.length - 1;
                        this.changeDataPathIdx -= 1;
                        this.resetOldDatas('filter');
                    },
                    DelayfilterData(val, DelayfilterTime = undefined) {
                        if (typeof (this.filterData) === 'function')
                            comFunc.delayExecFunc('__json_filterChange', () =>
                                setTimeout(() => {
                                        val && this.tipMsg('查询中');
                                        setTimeout(() => {
                                            this.filterData(val);
                                        }, 20);
                                    }, DelayfilterTime === undefined ? this.DelayfilterTime :
                                    DelayfilterTime));
                    },
                    filterData(val) {
                        if (this.notSet) {
                            this.tipMsg('数据未渲染，还不能搜索！');
                            return;
                        }
                        if (val && val.trim()) {
                            val = val.trim();
                            this.setOldDatas();
                            let c = 0;
                            let hasOldData = false;
                            const _find = (obj, findVal) => {
                                c++;
                                let result = undefined;
                                if (Array.isArray(obj)) {
                                    result = [];
                                    obj.forEach((o, idx) => {
                                        let rv = _find(o, findVal);
                                        if (rv) {
                                            rv[`原始数据_[${idx}]`] = o;
                                            result.push(rv); //rv
                                            hasOldData = true; //添加了原始数据 数据会多一层
                                        }
                                    });
                                    if (result.length === 0) return undefined;
                                    result = result.sort((a, b) => Object.keys(b).length - Object.keys(
                                        a).length);
                                } else if (typeof (obj) === 'object') {
                                    result = {};
                                    for (const key in obj) {
                                        if (this.findStr(key, findVal)) { //从key上面找 key有值就显示
                                            result[key] = obj[key];
                                        } else { //在值里面找
                                            let vResult = _find(obj[key], findVal);
                                            if (!vResult) continue; //值里面没有 就不显示
                                            result[key] = vResult;
                                        }
                                    }
                                    if (Object.keys(result).length === 0) result = undefined; //啥也没找到
                                } else {
                                    if (this.findStr(obj.toString(), findVal)) result = obj;
                                };
                                return result;
                            };
                            let _setData = this.getDataByChangeDataPath(this.getOldDatas()); //获得经过这个深度的对象
                            this.refresh(_find(_setData, val), undefined, false);
                            console.log(`---------------------${c}`); //运行find次数
                            this.tipMsg('查询已完成');
                            let tagDeep = this.maxDeep - (hasOldData ? 1 : 0);
                            [0, tagDeep].forEach((_deep, idx) =>
                                setTimeout(() => this.deep = _deep, idx * 10))
                            this.isInFilter = true;
                            //做查询操作
                        } else if (this.oldDatas) { //还原数据
                            this.resetOldDatas('filter');
                            this.isInFilter = false;
                        }
                    },
                    resetAndRefresh() { //还原数据并设置数据
                        this.$children[0].visible = false;
                        const oldFilter = this.filter;
                        this.oldDatas = {};
                        this.resetOldDatas();
                        this.filter = oldFilter;
                        this.refresh.apply(this, arguments);
                    },
                    refresh(data, _deep = undefined, isFilter = true, call = () => {}) { //切换数据时会有污染
                        this.$children[0].visible = false;
                        for (const title in this['datas'])
                            this.$delete(this['datas'], title);
                        let maxDeep = this.maxDeep = 0;
                        const dataChange = (_data, deep = 0) => {
                            try {
                                maxDeep = Math.max(deep, maxDeep);
                                //尝试把json字符串变成对象
                                _data = typeof (_data) === 'string' ? JSON.parse(_data) : _data;
                                for (const key in _data) {
                                    _data[key] = dataChange(_data[key], deep + 1);
                                }
                            } catch (e) {}
                            let arr = [];
                            if (typeof (_data) === 'string' && (arr = _data.split('\r\n')).length > 1) {
                                return arr;
                            }
                            return _data;
                        }
                        data = dataChange(data);
                        this.maxDeep = maxDeep;
                        if (_deep !== undefined) {
                            this.deep = _deep > maxDeep ? maxDeep : _deep;
                            let dps = this.$el.getElementsByClassName('deepSelect');
                            dps.length > 0 && this.$nextTick(() =>
                                dps[0]['selectedIndex'] = _deep - 1);
                        }
                        if (typeof (data) === 'string') {
                            this.$set(this['datas'], '文本值', data);
                        } else
                            for (const title in data) {
                                this.$set(this['datas'], title, data[title]);
                            }
                        this.$children[0].visible = true
                        if (isFilter) {
                            if (this.notSet) { //初次加载数据
                                while (this.changeDataPaths.length > 0)
                                    this.changeDataPaths.pop();
                                this.notSet = false;
                                this.placeholder = '俺是检索框 多条件空格分隔';
                                if (this.filter) { //还没加载数据就查询了
                                    this.tipMsg('查询ing');
                                    this.DelayfilterData(this.filter, 10);
                                }
                            } else if (this.filter) { //赋值时直接查询
                                this.DelayfilterData(this.filter, 10);
                            }
                        }
                        typeof (call) === 'function' && call()
                    },
                    selectDeepChange(val) {
                        this.deep = val.target.selectedIndex + 1;
                    },
                    toolShowCheckChange(e) {
                        $(this.$el).find('.tool').css('display',
                            (e.target.checked ? 'none' : ''));
                    },
                    jsonClosedCheckChange(e) {
                        this.closed = e.target.checked;
                    },
                    keyClick(el) { //左侧键被点击
                        if (typeof (KEYClick) === 'function') KEYClick(el);
                    },
                    valueClick(el) { //右侧value被点击
                        if (typeof (VALUEClick) === 'function') VALUEClick(el);
                    },
                    dbkeyClick(el) { //左侧键被点击
                        if (typeof (DBKEYClick) === 'function') DBKEYClick(el);
                    },
                    dbvalueClick(el) { //右侧value被点击
                        if (typeof (DBVALUEClick) === 'function') DBVALUEClick(el);
                    },
                    changeData(el) { //由于查询会 使用oldDatas作为查询的数据源 尽管这里切换了 却还是无效
                        //默认双击方法 把双击的key作为主数据
                        if (el.classList.contains('json-value')) { //对于value的表现是复制
                            comFunc.copyTxt($(el).text().trim().match('"(.+?)"')[1]);
                            return;
                        }
                        let curEl = $(el),
                            keyArr = [],
                            arrIdx = undefined;
                        const getCurWrap = (_el) => {
                            return $(_el).parents('.json-body:eq(0)').parent('.content-wrap:eq(0)');
                        };
                        const pushByEl = (_el) => {
                            let match = $(_el).text().match(/^\"(.+?)\"\:\s?$/);
                            if (match)
                                keyArr.push(`['${match[1]}']`);
                        }
                        let isFirst = true;
                        while ($(curEl).length > 0) {
                            let match = '';
                            if (isFirst) pushByEl(curEl);
                            let _curEl = getCurWrap(curEl).find('.json-key').eq(0);
                            if (getCurWrap(curEl)[0] === getCurWrap(_curEl)[0]) { //找到的元素和当前在一级别
                                if (curEl.parents('.content-wrap').length === 2) break; //最上面一级了
                                let bigs = getCurWrap(_curEl).parents('.json-body>.json-view-container').eq(
                                    0).parent().children('.json-view-container');
                                bigs.each((idx, el) => {
                                    if ($(el).has(_curEl).length > 0)
                                        arrIdx = idx; //这种情况当成数组处理
                                });
                                if (arrIdx !== undefined)
                                    keyArr.push(`[${arrIdx}]`);
                                curEl = bigs.eq(0).parents('.content-wrap').eq(0).find('.json-key').eq(0);
                                if (curEl[0] === _curEl[0]) //再往上一级
                                    curEl = bigs.eq(0).parents('.content-wrap').eq(1).find('.json-key').eq(
                                        0);
                                pushByEl(curEl);
                            } else {
                                curEl = _curEl;
                                pushByEl(curEl);
                            }
                            isFirst = false;
                        }
                        keyArr.reverse();
                        let _data = '',
                            _this = this,
                            curDataStr = '';
                        while ((typeof (_data) !== 'object' || !_data) && keyArr.length > 0) {
                            eval(`_data = _this.datas${curDataStr = (keyArr.join(''))}`);
                            keyArr.pop();
                        }
                        curDataStr && layer.confirm(`切换数据源到${curDataStr}?`, {
                            icon: 3,
                            title: '是否切换'
                        }, (index) => {
                            layer.close(index);
                            if (Object.keys(this.getOldDatas()).length === 0)
                                this.setOldDatas();
                            let olds = this.getDataByChangeDataPath();
                            while (this.changeDataPaths.pop());
                            this.changeDataPaths.push(olds);
                            this.changeDataPaths.push(curDataStr);
                            this.changeDataPathIdx = this.changeDataPaths.length - 1;
                            this.refresh(_data); //备份原来的数据 然后还原数据
                            this.tipMsg('切换完成');
                        });
                    }
                },
                created() {
                    this.$nextTick(() => {
                        let isNeedTip = false;
                        let elSelector = '#' + this.$el.id + ' #selectInput';
                        let tip = (msg) => this.tipMsg(msg, elSelector);
                        $(this.$el).parent().scroll(function () {
                            if ($(elSelector).val()) return;
                            var topp = $(this).scrollTop();
                            if (topp > 800 && isNeedTip) {
                                tip('翻累了的话可以试试查找功能~');
                                isNeedTip = false;
                            }
                            if (topp < 800 && Math.random() < 0.02) isNeedTip = true;
                        });
                    });
                    this.isBindClick && this.$nextTick(() => {
                        if (!this.fixedTool) $(this.$el).find('.tool').css('position', '');
                        $(this.$el).click(() => { //json-key是 左边点击
                            //.json-key,.json-value     span无class一般是盒子
                            let class_funcs = {
                                'json-key': this.keyClick,
                                'json-value': this.valueClick,
                            }
                            for (const css in class_funcs) {
                                if (event.target.classList.contains(css))
                                    class_funcs[css](event.target);
                            }
                        })
                        $(this.$el).dblclick(() => { //json-key是 左边点击
                            //.json-key,.json-value     span无class一般是盒子
                            let class_funcs = {
                                'json-key': this.dbkeyClick,
                                'json-value': this.dbvalueClick,
                            }
                            for (const css in class_funcs) {
                                if (event.target.classList.contains(css))
                                    class_funcs[css](event.target);
                            }
                            //双击切换数据源
                            if (this.allowDBChangeData === true) this.changeData(event
                                .target);
                        });
                        $(this.$el).mousemove((event) => { //鼠标移动
                            //.json-key,.json-value     span无class一般是盒子
                            const el = event.target;
                            let class_tips = {
                                'json-key': [],
                                'json-value': [],
                            }; //移动的时候 可以提示
                            let msg = '';
                            if (!this.notSet && typeof (GetElTipCall) === 'function' && (
                                    msg = GetElTipCall(el))) {
                                class_tips['json-key'].push(msg);
                            } else if (this.allowDBChangeData === true && !this.notSet) {
                                class_tips['json-key'].push('双击可以切换数据源');
                                class_tips['json-value'].push('双击可以复制');
                            } else {
                                if (typeof (DBKEYClick) === 'function' && !this.notSet)
                                    class_tips['json-key'].push('可双击');
                                if (typeof (DBVALUEClick) === 'function' && !this.notSet)
                                    class_tips['json-value'].push('可双击');
                            }
                            for (const css in class_tips) {
                                if (el.classList.contains(css))
                                    this.tipMsg(class_tips[css], el);
                                else if ($(el).attr('tips'))
                                    this.tipMsg($(el).attr('tips'), el);
                            }
                        });
                    });
                }
            });
        };
        const initDatas = {
            '提示1': 'order时带参数查询，速度会更快',
            '提示2': '点击单元格这里会显示数据',
        };
        const JsonCell = CreteJsonV('jsonCell', initDatas);
        const JsonRow = CreteJsonV('jsonRow', initDatas);
        $(JsonRow.$el).click(() => {
            console.log(event.target)
        }) //点击事件demo
        function backgrounds() {
            let css = [
                'linear-gradient(to right, rgb(18, 194, 233), rgb(196, 113, 237), rgb(246, 79, 89))',
                'linear-gradient(to right, rgb(198, 255, 221), rgb(251, 215, 134), rgb(247, 121, 125))',
                'linear-gradient(to right, rgb(41, 128, 185), rgb(109, 213, 250), rgb(255, 255, 255))',
                'linear-gradient(to right, rgb(204, 149, 192), rgb(219, 212, 180), rgb(122, 161, 210))',
                'linear-gradient(to right, rgb(221, 214, 243), rgb(250, 172, 168))',
                'linear-gradient(to right, rgb(201, 255, 191), rgb(255, 175, 189))',
                'linear-gradient(to right, rgb(151, 150, 240), rgb(251, 199, 212))',
                'linear-gradient(to right, rgb(255, 110, 127), rgb(191, 233, 255))',
            ]
            return css[parseInt(Math.random() * css.length)];
        }

        $(() => {
            // https://cn.vuejs.org/v2/guide/mixins.html
            //后续优化组件时 可以考虑用这种方案来优化 做功能划分
            // 定义一个混入对象

            // 定义一个使用混入对象的组件
            //var Component = Vue.extend({
            //    mixins: [myMixin]
            //})

            //var component = new Component() // => "hello from mixin!"
        });
    </script>
</body>

</html>